using BackOffice.Application.DTOs;
using Backoffice.Domain.Entities.App;
using Backoffice.Domain.Repositories;
using BackOffice.Domain.Entities.App;
using Backoffice.Application.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;

namespace BackOffice.Application.Services
{
    public class FileService : IFileService
    {
        private readonly IRepository<AppFile> _fileRepo;
        private readonly IRepository<AppFolder> _folderRepo;
        private readonly IRepository<AppFileShare> _fileShareRepo;
        private readonly IRepository<AppFileAcl> _fileAclRepo;
        private readonly ILogService _logService;

        public FileService(IRepository<AppFile> fileRepo, IRepository<AppFolder> folderRepo, IRepository<AppFileShare> fileShareRepo, IRepository<AppFileAcl> fileAclRepo, ILogService logService)
        {
            _fileRepo = fileRepo;
            _folderRepo = folderRepo;
            _fileShareRepo = fileShareRepo;
            _fileAclRepo = fileAclRepo;
            _logService = logService;
        }

        /* 文件相关 */
        public async Task<ApiResult> UploadFileAsync(UploadFileDto dto)
        {
            try
            {
                // 确保上传目录存在
                var uploadsDir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads");
                if (!Directory.Exists(uploadsDir))
                {
                    Directory.CreateDirectory(uploadsDir);
                }

                // 生成唯一的文件名
                var fileName = $"{Guid.NewGuid()}_{dto.FileName}";
                var relativePath = $"/uploads/{fileName}";
                var fullPath = Path.Combine(uploadsDir, fileName);

                // 如果有文件内容，保存到磁盘
                if (!string.IsNullOrEmpty(dto.FileContent))
                {
                    var fileBytes = Convert.FromBase64String(dto.FileContent);
                    await System.IO.File.WriteAllBytesAsync(fullPath, fileBytes);
                }

                var file = new AppFile(dto.FileName, dto.FileSize, dto.FileExtension, dto.MimeType, relativePath, dto.FolderId, dto.Description);
                await _fileRepo.CreateAsync(file);
                
                // 记录文件上传日志
                try
                {
                    await _logService.RecordLogAsync(new LogRecordDto(
                        "系统",
                        "上传文件",
                        $"上传文件: {dto.FileName}",
                        "127.0.0.1",
                        "Unknown"
                    ));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"记录文件上传日志失败: {ex.Message}");
                }
                
                return ApiResult.Success(file, "文件上传成功");
            }
            catch (Exception ex)
            {
                return ApiResult.Fail($"文件上传失败: {ex.Message}", 3001);
            }
        }

        public async Task<ApiResult> UpdateFileAsync(Guid id, UpdateFileDto dto)
        {
            var file = await _fileRepo.GetByIdAsync(id);
            if (file == null) return ApiResult.Fail("文件不存在", 3003);

            file.UpdateDesc(dto.Description); // 使用正确的 UpdateDesc 方法
#pragma warning disable CS8604 // 引用类型参数可能为 null。
            file.Rename(dto.FileName);
#pragma warning restore CS8604 // 引用类型参数可能为 null。
            await _fileRepo.UpdateAsync(file);
            return ApiResult.Success(file, "文件更新成功");
        }

        public async Task<ApiResult> DeleteFileAsync(Guid id)
        {
            var file = await _fileRepo.GetByIdAsync(id);
            if (file == null) return ApiResult.Fail("文件不存在", 3003);

            var fileName = file.FileName; // 保存文件名用于日志记录
            await _fileRepo.DeleteAsync(file.Id);
            
            // 记录文件删除日志
            try
            {
                await _logService.RecordLogAsync(new LogRecordDto(
                    "系统",
                    "删除文件",
                    $"删除文件: {fileName}",
                    "127.0.0.1",
                    "Unknown"
                ));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"记录文件删除日志失败: {ex.Message}");
            }
            
            return ApiResult.Success(null, "文件删除成功");
        }

        public async Task<ApiResult> GetFileListAsync(Guid? folderId)
        {
            var list = await _fileRepo.GetAllAsync();
            if (folderId.HasValue)
            {
                list = list.Where(f => f.FolderId == folderId.Value).ToList();
            }
            return ApiResult.Success(list, "文件列表获取成功");
        }

        public async Task<ApiResult> MoveFileAsync(Guid id, Guid? targetFolderId)
        {
            var file = await _fileRepo.GetByIdAsync(id);
            if (file == null) return ApiResult.Fail("文件不存在", 3003);

            file.Move(targetFolderId);
            await _fileRepo.UpdateAsync(file);
            return ApiResult.Success(file, "文件移动成功");
        }

        /* 文件夹相关 */
        public async Task<ApiResult> CreateFolderAsync(CreateFolderDto dto)
        {
            var folder = new AppFolder(dto.Name, dto.Description, dto.ParentId);
            await _folderRepo.CreateAsync(folder);
            return ApiResult.Success(folder, "文件夹创建成功");
        }

        public async Task<ApiResult> UpdateFolderAsync(Guid id, UpdateFolderDto dto)
        {
            var folder = await _folderRepo.GetByIdAsync(id);
            if (folder == null) return ApiResult.Fail("文件夹不存在", 3004);

            folder.Rename(dto.Name);
            folder.UpdateDesc(dto.Description);
            await _folderRepo.UpdateAsync(folder);
            return ApiResult.Success(folder, "文件夹更新成功");
        }

        public async Task<ApiResult> DeleteFolderAsync(Guid id)
        {
            var folder = await _folderRepo.GetByIdAsync(id);
            if (folder == null) return ApiResult.Fail("文件夹不存在", 3004);

            await _folderRepo.DeleteAsync(folder.Id);
            return ApiResult.Success(null, "文件夹删除成功");
        }

        public async Task<ApiResult> GetFolderTreeAsync(Guid? parentId = null)
        {
            var list = await _folderRepo.GetAllAsync();
            if (parentId.HasValue)
            {
                list = list.Where(f => f.ParentId == parentId.Value).ToList();
            }
            return ApiResult.Success(list, "文件夹树获取成功");
        }

        /* 分享 & 权限 */
        public async Task<ApiResult> ShareFileAsync(Guid fileId, ShareFileDto dto)
        {
            var file = await _fileRepo.GetByIdAsync(fileId);
            if (file == null) return ApiResult.Fail("文件不存在", 3003);

            var share = new AppFileShare(fileId, dto.SharedTo, dto.ExpireAt, dto.Mode);
            await _fileShareRepo.CreateAsync(share);
            return ApiResult.Success(share, "文件分享成功");
        }

        public async Task<ApiResult> RevokeShareAsync(Guid shareId)
        {
            var share = await _fileShareRepo.GetByIdAsync(shareId);
            if (share == null) return ApiResult.Fail("分享记录不存在", 3005);

            await _fileShareRepo.DeleteAsync(share.Id);
            return ApiResult.Success(null, "分享撤销成功");
        }

        public async Task<ApiResult> SetFileAclAsync(Guid fileId, SetFileAclDto dto)
        {
            var file = await _fileRepo.GetByIdAsync(fileId);
            if (file == null) return ApiResult.Fail("文件不存在", 3003);

            // 显式使用 BackOffice.Domain.Entities.App.FileAccess 枚举
            var acl = new AppFileAcl(fileId, dto.UserId, (BackOffice.Domain.Entities.App.FileAccess)dto.Access);

            await _fileAclRepo.CreateAsync(acl);
            return ApiResult.Success(acl, "文件权限设置成功");
        }
        public async Task<ApiResult> SearchFilesAsync(FileSearchDto dto)
        {
            var query = _fileRepo.Query();
            if (!string.IsNullOrEmpty(dto.FileName))
                query = query.Where(f => f.FileName.Contains(dto.FileName));
            if (!string.IsNullOrEmpty(dto.FileExtension))
                query = query.Where(f => f.FileExtension == dto.FileExtension);
            if (!string.IsNullOrEmpty(dto.Description))
                query = query.Where(f => f.Description != null && f.Description.Contains(dto.Description));
            if (dto.FolderId.HasValue)
                query = query.Where(f => f.FolderId == dto.FolderId);
            if (!string.IsNullOrEmpty(dto.MimeType))
                query = query.Where(f => f.MimeType == dto.MimeType);
            if (dto.MinSize.HasValue)
                query = query.Where(f => f.FileSize >= dto.MinSize.Value);
            if (dto.MaxSize.HasValue)
                query = query.Where(f => f.FileSize <= dto.MaxSize.Value);
            if (dto.CreatedFrom.HasValue)
                query = query.Where(f => f.CreatedAt >= dto.CreatedFrom.Value);
            if (dto.CreatedTo.HasValue)
                query = query.Where(f => f.CreatedAt <= dto.CreatedTo.Value);
        
            var result = await query.ToListAsync();
            return ApiResult.Success(result);
        }
    }
}